package math.vectorSpace.R3.visualization;

import math.vectorSpace.R2.Point2D;
import math.vectorSpace.R2.Vector2D;
import math.vectorSpace.R3.Line3D;
import math.vectorSpace.R3.Plane3D;
import math.vectorSpace.R3.Point3D;
import math.vectorSpace.R3.Vector3D;

public class RenderPerspective extends Render3D {

    private Point3D vanishingPoint;

    public RenderPerspective(double angleXY, double angleZ,
            int distance, int screenWidth, int screenHeight) {
        super(angleXY, angleZ, distance, screenWidth, screenHeight);
        this.vanishingPoint = new Point3D(new Vector3D(
                this.planeCenter).invert());
    }

    public double getFocalLength() {
        return vanishingPoint.distance(planeCenter);
    }

    /**
     * Same as the intersect in Line3D.intersect(Plane3D) except
     * the case where the line lies on the plane is not checked
     * since that case that will never occur in this program.
     * This was done to speed up the rendering process.
     * 
     * @param line 
     * @param plane
     * @return a Point3D that describes the intersection between the given
     *         line and the given plane.
     */
    private static Point3D intersect(Line3D line, Plane3D plane) {
        double t = -((plane.getA() * line.getRefPoint().getX())
                + (plane.getB() * line.getRefPoint().getY())
                + (plane.getC() * line.getRefPoint().getZ()) + plane.getD())
                / ((plane.getA() * line.getDirVector().getX()) + (plane.getB() * line.getDirVector().getY())
                + (plane.getC() * line.getDirVector().getZ()));
        return line.evaluateAt(t);
    }

    @Override
    public Point2D project(Point3D point) {
        Line3D line = new Line3D(vanishingPoint, point);
        Vector3D intersection = new Vector3D(
                line.intersect(new Plane3D(xBasis, yBasis)));

        return new Point2D(intersection.projectMag(xBasis),
                intersection.projectMag(yBasis));
    }
}
